九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、この数ヶ月はChatGPT
に代表する生成AIが一般的に広がったので、私も例にもれずドップリと体験することになりました。
そして、そんな中で「あ、これは個人サービスにもあると便利だな」と思う機能に遭遇しました。
それは・・・・・・
ウィッシュリスト
です。
ウィッシュリストとは、例えば「まだこのサイトはリリースまで時間があるけど、リリースしたらお知らせするよ👍」という機能になります。
※ これは、ChatGPT
やBard
でも採用されてましたよね。
そして、このウィッシュリストがなぜプラスなのかというと・・・・・・
リリース先に需要を知ることができるから
です。
つまり、ウィッシュリストが多く集まればみんなが欲しがっているということになりますし、その逆の場合は「あれ!?自分の中では盛り上がってたけど、みんなは好きじゃないのね…」という判断ができるからです。(👈これクラウドファンディングや受注生産と同じ作戦ですね)
そこで❗
今回は「Laravel 10.x + React」を使ってこの「ウィッシュリスト」機能をつくってみたいと思います。
ぜひ何かの参考になりましたら嬉しいです。😄✨
「左右5本ずつじゃなく、
10本の指を1つの意識で
ピアノ演奏できるよう研究中です」
開発環境: Laravel 10.x、React、Inertia.js、TailwindCSS、Vite
目次
モデル&マイグレーションを用意する
では、まずはDB
周りを用意します。
以下のコマンドを実行してください。
php artisan make:model Wishlist -m
すると、モデルとマイグレーションのファイルが作成されるので中身をそれぞれ次のように変更します。
app/Models/Wishlist.php
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Wishlist extends Model { use HasFactory; protected $guarded = ['id']; // 👈ここを追加しました }
そして、マイグレーションです。
database/migrations/****_**_**_******_create_wishlists_table.php
// 省略 public function up(): void { Schema::create('wishlists', function (Blueprint $table) { $table->id(); $table->string('email')->comment('メールアドレス'); $table->text('memo')->nullable()->comment('メモ'); $table->timestamps(); }); } // 省略
では、この状態でテーブルを追加します。
以下のコマンドを実行してください。
php artisan migrate
すると、実際のテーブルはこうなりました。
コントローラーをつくる
続いて、ウィッシュリストの登録フォームをつくっていきます。
以下のコマンドを実行してください。
php artisan make:controller WishlistController
すると、ファイルが作成されるので中身を次のようにします。
app/Http/Controllers/WishlistController.php
<?php namespace App\Http\Controllers; use App\Models\Wishlist; use Illuminate\Http\Request; use Inertia\Inertia; class WishlistController extends Controller { public function create() { return Inertia::render('Wishlist/Create'); } public function store(Request $request) { $request->validate([ 'email' => 'required|email', ]); $wishlist = Wishlist::firstOrNew([ 'email' => $request->email, ]); $wishlist->email = $request->email; $wishlist->memo = $request->memo; $wishlist->save(); return redirect()->route('wishlist.create')->with('message', 'ウィッシュリストが登録されました!'); } }
この中では、create()
がウィッシュリストの登録フォームで、store()
がその送信先になっています。
フラッシュメッセージが React 側で受け取れるようにする
なお、先ほどコントローラー内で以下のようなコードがあったと思います。
return redirect()->route('wishlist.create')->with('message', 'ウィッシュリストが登録されました!');
意味としては、指定したURL
にリダイレクトするというものですが、それと同時に「フラッシュメッセージ」もセットしています。
フラッシュメッセージとは、今回のように「登録が完了しました」というような一時的なメッセージのことで、これは「セッション」と呼ばれる箱で保持されます。そして、リダイレクトした先でそのデータを取り出すことができるというわけですね。
しかし、Laravel
でセットされたデータをInertia + React
で受け取るためには以下のようなひと手間必要になるので、先に追加しておいてください。
app/Providers/AppServiceProvider.php
// 省略 public function boot(): void { // 👇 ここを追加しました Inertia::share('flash', function (Request $request) { return [ 'message' => $request->session()->get('message'), ]; }); } // 省略
そして、次の項目でご紹介しますが、React
内では以下のようにしてそのデータを取得することができるようになります。
import { usePage } from '@inertiajs/react' // 省略 const { flash } = usePage().props;
ビューをつくる
では、WishlistController
コントローラー内で指定した登録フォームのビュー(React
)をつくっていきます。
以下のファイルを作成してください。
resources/js/Pages/Wishlist/Create.jsx
import { useForm, usePage } from '@inertiajs/react' export default function Create() { // データ const { data, setData, post, reset, processing, errors } = useForm({ email: '', memo: '', }); const handleChange = (e) => { const key = e.target.id; const value = e.target.value; setData(values => ({ ...values, [key]: value, })) } // 送信 const submit = (e) => { e.preventDefault(); const url = route('wishlist.store'); post(url, { data, onSuccess: () => reset('email', 'memo') // 入力をリセット }); }; // フラッシュメッセージ const { flash } = usePage().props; return ( <div className="container mx-auto px-4 sm:px-6 lg:px-8 py-12"> {flash.message && ( <div className="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative mb-6" role="alert"> <span className="block sm:inline">{flash.message}</span> </div> )} <h1 className="text-3xl font-bold text-center mb-6">ウィッシュリスト作成</h1> <form onSubmit={submit} className="w-full max-w-lg mx-auto"> <div className="flex flex-wrap -mx-3 mb-6"> <label htmlFor="email" className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"> メールアドレス: </label> <input id="email" type="email" value={data.email} onChange={handleChange} className="appearance-none block w-full bg-gray-200 text-gray-700 border-none rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" /> {errors.email && <p className="text-red-500 text-xs italic">{errors.email}</p>} </div> <div className="flex flex-wrap -mx-3 mb-6"> <label htmlFor="memo" className="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2"> その他欲しい機能などがありましたら入力してください<small>(任意):</small> </label> <textarea id="memo" value={data.memo} onChange={handleChange} className="appearance-none block w-full h-auto bg-gray-200 text-gray-700 border-none rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white" /> </div> <div className="flex items-center justify-between"> <button type="submit" className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" disabled={processing} > 送信 </button> </div> </form> </div> ) }
ちなみに、いつもはReact
っぽさを出したいのでuseState
を使っていますが、今回はInertia
が用意してくれているuseForm()
を使ってみました。確かにこれも便利ですね👍
ということで、これでフォームからデータ送信すると「wishlists」テーブルにデータが登録されていくようになります。
メール送信をキューに登録できる Artisan コマンドをつくる
では、ここからの想定はサイトの開発が完了し、リリース段階になったものとして作業を進めます。
まずはウィッシュリストに登録されたメールアドレスをキューに登録できるようにします。
「キュー」というのは、とてもシンプルに言うと「ちょっとずつ実行する」機能です。
例えば、一気に大量のメール送信するしようとすると、途中で止まったりメモリ不足になったりして都合が悪いのでこれを分散して実行しようね、というものです。
ということで、まずは独自のArtisan
コマンドをつくってウィッシュリストのメールアドレスをこの「キュー」に登録できるようにしましょう。
以下のコマンドを実行してください。
php artisan make:command QueueWelcomeEmails
すると、ファイルが作成されるので、中身を次のようにします。
app/Console/Commands/QueueWelcomeEmails.php
<?php namespace App\Console\Commands; use App\Models\Wishlist; use App\Mail\WelcomeEmail; use Illuminate\Console\Command; use Illuminate\Support\Facades\Mail; class QueueWelcomeEmails extends Command { /** * The name and signature of the console command. * * @var string */ protected $signature = 'queue:welcome-emails'; /** * The console command description. * * @var string */ protected $description = 'ウィッシュリストのメールをキューに登録する'; /** * Execute the console command. */ public function handle() { $wishlists = Wishlist::query() ->whereNull('queued_at') ->limit(1000) ->get(); $now = now(); foreach ($wishlists as $wishlist) { // キューに登録 Mail::to($wishlist->email)->queue(new WelcomeEmail()); $wishlist->queued_at = $now; $wishlist->save(); } $this->info('Done!'); return Command::SUCCESS; } }
この中では、登録されたウィッシュリストの中から最大1000
件をキューに登録するようになっています。
実際の実行は、php artisan queue:welcome-emails
とコマンド実行するだけでOK
です。
なお、キューはコマンドを実行すると基本的にずっと待機してくれてjobs
テーブルにデータが入ってくるとすぐ実行されます。
そのため、このコマンドは基本的にcrontab
などで定期実行することを想定しています。(今回はウィッシュリストの数が少ないので1回で完了します)
メール送信する部分をつくる
先ほどのqueue:welcome-emails
コマンドで指定した「WelcomeEmail」をLaravel
のメール送信機能「Mailable」で作っていきます。
以下のコマンドを実行してください。
php artisan make:mail WelcomeEmail
するとMailable
ファイルが作成されるので中身を変更します。
app/Mail/WelcomeEmail.php
// 省略 class WelcomeEmail extends Mailable { // 省略 public function envelope(): Envelope { return new Envelope( subject: 'ついにリリースされました!', ); } public function content(): Content { return new Content( view: 'emails.welcome', ); } // 省略
そして、メール本文は以下のファイルになります。
resources/views/emails/welcome.blade.php
<h1>ついにリリースされました!</h1> <p> 以下のURLからユーザー登録していただけます。<br><br> <a href="{{ $url }}">(サイト名)</a> </p>
キューをデータベースで管理できるようにする
Laravel
ではいろいろなキューの実行方法がありますが、シンプルなので今回はデータベースを使った方法にします。
そこで、キューをDB
で管理できるよう次の作業をしてください。
まずは以下2つのコマンドを実行します。
php artisan queue:table
php artisan migrate
すると、jobs
というテーブルが作成されます。
実際のテーブルはこうなります。
そして、「データベースを使ったキュー」を有効にするため.env
を変更します。
QUEUE_CONNECTION=database
これでDB
のキューが有効になりました。
これで作業はすべて完了です。
お疲れ様でした😄✨
テストしてみる
では、実際にテストしてみましょう❗
まずはVite
を起動して「https://******/wishlist/create」にアクセスしてみましょう。
※ なお、今回はメール送信テストにmailcatcher
を使いますので、これも起動しておきました。
すると、以下のような表示になりました。
では、このフォームから以下3つのメールアドレスを登録してみます。
- taro@example.com
- jiro@example.com
- saburo@example.com
では、登録が終わったのでDB
テーブルを確認してみましょう。
はい❗
うまく登録されていますね😄
では、サイトがリリースされたものとして、メールキューを実行してみます。
まずは以下のコマンドを実行してキューの実行を待機させておきます。
php artisan queue:work
すると、以下のような表示になりました。
では、この状態で(このコマンドは止めず、別のコマンドとして)以下を実行してみましょう。
php artisan queue:welcome-emails
すると・・・・・・
はい❗
何も手動では実行していませんが、キューが実行されました。
では、メールの方も確認してみましょう。
はい❗
うまく3人に「ウェルカムメール」が送信されてました。
すべて成功です😄✨
企業様へのご提案
今回のように「ウィッシュリスト」機能を活用すると以下のようなメリットがあります。
- サイトリリースだけでなく、機能のリリース前にウィッシュリストをつくることで本当に作成すべきかどうか(ユーザーが望んでいるのかどうか)を知ることができる
- 今回のようにウィッシュリストのフォームに要望などの入力を用意することで、さらにユーザーが何を求めているのかを知ることができる
- もしもウィッシュリストへの登録が少なかった場合でも、それは「ニーズがなかった」という判断ができ、お金だけでなく時間のコストを最小限にして撤退することができる
もしこういった機能をご希望でしたら、ぜひお問い合わせからご相談ください。
お待ちしております。😄✨
おわりに
ということで、今回は「Laravel + React」でウィッシュリスト機能をつくってみました。
正直なところ、個人サービスはお金をかけにくい側面もあると思うので、ランディングページとウィッシュリスト・フォームだけをつくってユーザーの反応を見るというのも良い作戦じゃないかと考えています。
また、たくさんアイデアがある場合も、アイデアごとにランディングページをサブドメインで大量につくり、ウィッシュリストの反応の良かったプロジェクトだけ実際にサイト化するというのも理にかなった方法かもしれませんね。(この場合ウェブ広告などを併用する必要があると思うので、多少コストはかかりますが…😅)
ぜひみなさんも色々とウィッシュリストの使い方を考えてみてくださいね。
ではでは〜❗
「姪っ子がいたずらで
驚かしてきた結果、
ちょっと腰をいためました😂」